home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Utilities / BasiliskII / src / Unix / video_blit.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-31  |  12.0 KB  |  358 lines

  1. /*
  2.  *  video_blit.cpp - Video/graphics emulation, blitters
  3.  *
  4.  *  Basilisk II (C) 1997-2001 Christian Bauer
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. #include "sysdeps.h"
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <X11/Xlib.h>
  26. #include <X11/Xutil.h>
  27.  
  28. #ifdef ENABLE_VOSF
  29. // Format of the target visual
  30. struct VisualFormat {
  31.     int        depth;                    // Screen depth
  32.     uint32    Rmask, Gmask, Bmask;    // RGB mask values
  33.     uint32    Rshift, Gshift, Bshift;    // RGB shift values
  34. };
  35. static VisualFormat visualFormat;
  36.  
  37. /* -------------------------------------------------------------------------- */
  38. /* --- Raw Copy / No conversion required                                  --- */
  39. /* -------------------------------------------------------------------------- */
  40.  
  41. static void Blit_Copy_Raw(uint8 * dest, const uint8 * source, uint32 length)
  42. {
  43.     // This function is likely to be inlined and/or highly optimized
  44.     memcpy(dest, source, length);
  45. }
  46.  
  47. /* -------------------------------------------------------------------------- */
  48. /* --- RGB 555                                                            --- */
  49. /* -------------------------------------------------------------------------- */
  50.  
  51. #ifdef WORDS_BIGENDIAN
  52. # define FB_FUNC_NAME Blit_RGB555_OBO
  53. #else
  54. # define FB_FUNC_NAME Blit_RGB555_NBO
  55. #endif
  56.  
  57. #define FB_BLIT_1(dst, src) \
  58.     (dst = (((src) >> 8) & 0xff) | (((src) & 0xff) << 8))
  59.     
  60. #define FB_BLIT_2(dst, src) \
  61.     (dst = (((src) >> 8) & 0x00ff00ff) | (((src) & 0x00ff00ff) << 8))
  62.  
  63. #define    FB_DEPTH 15
  64. #include "video_blit.h"
  65.  
  66. /* -------------------------------------------------------------------------- */
  67. /* --- BGR 555                                                            --- */
  68. /* -------------------------------------------------------------------------- */
  69.  
  70. #ifdef WORDS_BIGENDIAN
  71.  
  72. // Native byte order
  73.  
  74. #define FB_BLIT_1(dst, src) \
  75.     (dst = (((src) >> 10) & 0x001f) | ((src) & 0x03e0) | (((src) << 10) & 0x7c00))
  76.  
  77. #define FB_BLIT_2(dst, src) \
  78.     (dst = (((src) >> 10) & 0x001f001f) | ((src) & 0x03e003e0) | (((src) << 10) & 0x7c007c00))
  79.  
  80. #define FB_DEPTH 15
  81. #define FB_FUNC_NAME Blit_BGR555_NBO
  82. #include "video_blit.h"
  83.  
  84. // Opposite byte order (untested)
  85.  
  86. #define FB_BLIT_1(dst, src) \
  87.     (dst = (((src) >> 2) & 0x1f00) | (((src) >> 8) & 3) | (((src) << 8) & 0xe000) | (((src) << 2) & 0x7c))
  88.  
  89. #define FB_BLIT_2(dst, src) \
  90.     (dst = (((src) >> 2) & 0x1f001f00) | (((src) >> 8) & 0x30003) | (((src) << 8) & 0xe000e000) | (((src) << 2) & 0x7c007c))
  91.  
  92. #define FB_DEPTH 15
  93. #define FB_FUNC_NAME Blit_BGR555_OBO
  94. #include "video_blit.h"
  95.  
  96. #else
  97.  
  98. // Native byte order (untested)
  99.  
  100. #define FB_BLIT_1(dst, src) \
  101.     (dst = (((src) >> 2) & 0x1f) | (((src) >> 8) & 0xe0) | (((src) << 8) & 0x0300) | (((src) << 2) & 0x7c00))
  102.  
  103. #define FB_BLIT_2(dst, src) \
  104.     (dst = (((src) >> 2) & 0x1f001f) | (((src) >> 8) & 0xe000e0) | (((src) << 8) & 0x03000300) | (((src) << 2) & 0x7c007c00))
  105.  
  106. #define FB_DEPTH 15
  107. #define FB_FUNC_NAME Blit_BGR555_NBO
  108. #include "video_blit.h"
  109.  
  110. // Opposite byte order (untested)
  111.  
  112. #define FB_BLIT_1(dst, src) \
  113.     (dst = (((src) << 6) & 0x1f00) | ((src) & 0xe003) | (((src) >> 6) & 0x7c))
  114.  
  115. #define FB_BLIT_2(dst, src) \
  116.     (dst = (((src) << 6) & 0x1f001f00) | ((src) & 0xe003e003) | (((src) >> 6) & 0x7c007c))
  117.  
  118. #define FB_DEPTH 15
  119. #define FB_FUNC_NAME Blit_BGR555_OBO
  120. #include "video_blit.h"
  121.  
  122. #endif
  123.  
  124. /* -------------------------------------------------------------------------- */
  125. /* --- RGB 565                                                            --- */
  126. /* -------------------------------------------------------------------------- */
  127.  
  128. #ifdef WORDS_BIGENDIAN
  129.  
  130. // Native byte order
  131.  
  132. #define FB_BLIT_1(dst, src) \
  133.     (dst = (((src) & 0x1f) | (((src) << 1) & 0xffc0)))
  134.  
  135. #define FB_BLIT_2(dst, src) \
  136.     (dst = (((src) & 0x001f001f) | (((src) << 1) & 0xffc0ffc0)))
  137.  
  138. #define FB_DEPTH 16
  139. #define FB_FUNC_NAME Blit_RGB565_NBO
  140. #include "video_blit.h"
  141.  
  142. // Opposite byte order
  143.  
  144. #define FB_BLIT_1(dst, src) \
  145.     (dst = ((((src) >> 7) & 0xff) | (((src) << 9) & 0xc000) | (((src) << 8) & 0x1f00)))
  146.  
  147. #define FB_BLIT_2(dst, src) \
  148.     (dst = ((((src) >> 7) & 0x00ff00ff) | (((src) << 9) & 0xc000c000) | (((src) << 8) & 0x1f001f00)))
  149.  
  150. #define FB_DEPTH 16
  151. #define FB_FUNC_NAME Blit_RGB565_OBO
  152. #include "video_blit.h"
  153.  
  154. #else
  155.  
  156. // Native byte order
  157.  
  158. #define FB_BLIT_1(dst, src) \
  159.     (dst = (((src) >> 8) & 0x001f) | (((src) << 9) & 0xfe00) | (((src) >> 7) & 0x01c0))
  160.     
  161. // gb-- Disabled because I don't see any improvement
  162. #if 0 && defined(__i386__) && defined(X86_ASSEMBLY)
  163.  
  164. #define FB_BLIT_2(dst, src) \
  165.     __asm__ (    "movl %0,%%ebx\n\t" \
  166.                 "movl %0,%%ebp\n\t" \
  167.                 "andl $0x1f001f00,%%ebx\n\t" \
  168.                 "andl $0x007f007f,%0\n\t" \
  169.                 "andl $0xe000e000,%%ebp\n\t" \
  170.                 "shrl $8,%%ebx\n\t" \
  171.                 "shrl $7,%%ebp\n\t" \
  172.                 "shll $9,%0\n\t" \
  173.                 "orl %%ebx,%%ebp\n\t" \
  174.                 "orl %%ebp,%0\n\t" \
  175.             : "=r" (dst) : "0" (src) : "ebx", "ebp", "cc" )
  176.  
  177. #else
  178.  
  179. #define FB_BLIT_2(dst, src) \
  180.     (dst = (((src) >> 8) & 0x001f001f) | (((src) << 9) & 0xfe00fe00) | (((src) >> 7) & 0x01c001c0))
  181.  
  182. #endif
  183.  
  184. #define FB_DEPTH 16
  185. #define FB_FUNC_NAME Blit_RGB565_NBO
  186. #include "video_blit.h"
  187.  
  188. // Opposite byte order (untested)
  189.  
  190. #define FB_BLIT_1(dst, src) \
  191.     (dst = (((src) & 0x1f00) | (((src) << 1) & 0xe0fe) | (((src) >> 15) & 1)))
  192.  
  193. #define FB_BLIT_2(dst, src) \
  194.     (dst = (((src) & 0x1f001f00) | (((src) << 1) & 0xe0fee0fe) | (((src) >> 15) & 0x10001)))
  195.  
  196. #define FB_DEPTH 16
  197. #define FB_FUNC_NAME Blit_RGB565_OBO
  198. #include "video_blit.h"
  199.  
  200. #endif
  201.  
  202. /* -------------------------------------------------------------------------- */
  203. /* --- RGB 888                                                            --- */
  204. /* -------------------------------------------------------------------------- */
  205.  
  206. #ifdef WORDS_BIGENDIAN
  207. # define FB_FUNC_NAME Blit_RGB888_OBO
  208. #else
  209. # define FB_FUNC_NAME Blit_RGB888_NBO
  210. #endif
  211.  
  212. #define FB_BLIT_2(dst, src) \
  213.     (dst = (((src) >> 24) & 0xff) | (((src) >> 8) & 0xff00) | (((src) & 0xff00) << 8) | (((src) & 0xff) << 24))
  214.  
  215. #define FB_DEPTH 24
  216. #include "video_blit.h"
  217.  
  218. /* -------------------------------------------------------------------------- */
  219. /* --- BGR 888                                                            --- */
  220. /* -------------------------------------------------------------------------- */
  221.  
  222. // Native byte order [BE] (untested)
  223.  
  224. #ifdef WORDS_BIGENDIAN
  225.  
  226. #define FB_BLIT_2(dst, src) \
  227.     (dst = (((src) >> 16) & 0xff) | ((src) & 0xff00) | (((src) & 0xff) << 16))
  228.  
  229. #define FB_FUNC_NAME Blit_BGR888_NBO
  230. #define FB_DEPTH 24
  231. #include "video_blit.h"
  232.  
  233. #else
  234.  
  235. // Opposite byte order [LE] (untested)
  236.  
  237. #define FB_BLIT_2(dst, src) \
  238.     (dst = (((src) >> 16) & 0xff) | ((src) & 0xff0000) | (((src) & 0xff) << 16))
  239.  
  240. #define FB_FUNC_NAME Blit_BGR888_OBO
  241. #define FB_DEPTH 24
  242. #include "video_blit.h"
  243.  
  244. #endif
  245.  
  246. // Opposite byte order [BE] (untested) / Native byte order [LE] (untested)
  247.  
  248. #ifdef WORDS_BIGENDIAN
  249. # define FB_FUNC_NAME Blit_BGR888_OBO
  250. #else
  251. # define FB_FUNC_NAME Blit_BGR888_NBO
  252. #endif
  253.  
  254. #define FB_BLIT_2(dst, src) \
  255.     (dst = ((src) & 0xff00ff) | (((src) & 0xff00) << 16))
  256.  
  257. #define FB_DEPTH 24
  258. #include "video_blit.h"
  259.  
  260. /* -------------------------------------------------------------------------- */
  261. /* --- Blitters to the host frame buffer, or XImage buffer                --- */
  262. /* -------------------------------------------------------------------------- */
  263.  
  264. // Function used to update the hosst frame buffer (DGA), or an XImage buffer (WIN)
  265. // --> Shall be initialized only through the Screen_blitter_init() function
  266. typedef void (*Screen_blit_func)(uint8 * dest, const uint8 * source, uint32 length);
  267. Screen_blit_func Screen_blit = 0;
  268.  
  269. // Structure used to match the adequate framebuffer update function
  270. struct Screen_blit_func_info {
  271.     int                    depth;            // Screen depth
  272.     uint32                Rmask;            // Red mask
  273.     uint32                Gmask;            // Green mask
  274.     uint32                Bmask;            // Blue mask
  275.     Screen_blit_func    handler_nbo;    // Update function (native byte order)
  276.     Screen_blit_func    handler_obo;    // Update function (opposite byte order)
  277. };
  278.  
  279. // Table of visual formats supported and their respective handler
  280. static Screen_blit_func_info Screen_blitters[] = {
  281. #ifdef WORDS_BIGENDIAN
  282.     {  1, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw    , Blit_Copy_Raw        },    // NT
  283.     {  8, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw    , Blit_Copy_Raw        },    // OK (NBO)
  284.     { 15, 0x007c00, 0x0003e0, 0x00001f, Blit_Copy_Raw    , Blit_RGB555_OBO    },    // OK (OBO)
  285.     { 15, 0x00001f, 0x0003e0, 0x007c00, Blit_BGR555_NBO    , Blit_BGR555_OBO    },    // NT
  286.     { 16, 0x00f800, 0x0007e0, 0x00001f, Blit_RGB565_NBO    , Blit_RGB565_OBO    },    // OK (OBO)
  287.     { 24, 0xff0000, 0x00ff00, 0x0000ff, Blit_Copy_Raw    , Blit_RGB888_OBO    },    // OK (OBO)
  288.     { 24, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO    , Blit_BGR888_OBO    },    // NT
  289.     { 32, 0xff0000, 0x00ff00, 0x0000ff, Blit_Copy_Raw    , Blit_RGB888_OBO    },    // OK
  290.     { 32, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO    , Blit_BGR888_OBO    }    // OK
  291. #else
  292.     {  1, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw    , Blit_Copy_Raw        },    // NT
  293.     {  8, 0x000000, 0x000000, 0x000000, Blit_Copy_Raw    , Blit_Copy_Raw        },    // OK (NBO)
  294.     { 15, 0x007c00, 0x0003e0, 0x00001f, Blit_RGB555_NBO    , Blit_Copy_Raw        },    // OK (NBO)
  295.     { 15, 0x00001f, 0x0003e0, 0x007c00, Blit_BGR555_NBO    , Blit_BGR555_OBO    },    // NT
  296.     { 16, 0x00f800, 0x0007e0, 0x00001f, Blit_RGB565_NBO    , Blit_RGB565_OBO    },    // OK (NBO)
  297.     { 24, 0xff0000, 0x00ff00, 0x0000ff, Blit_RGB888_NBO    , Blit_Copy_Raw        },    // OK (NBO)
  298.     { 24, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO    , Blit_BGR888_OBO    },    // NT
  299.     { 32, 0xff0000, 0x00ff00, 0x0000ff, Blit_RGB888_NBO    , Blit_Copy_Raw        },    // OK (NBO)
  300.     { 32, 0x0000ff, 0x00ff00, 0xff0000, Blit_BGR888_NBO    , Blit_BGR888_OBO    }    // NT
  301. #endif
  302. };
  303.  
  304. // Initialize the framebuffer update function
  305. // Returns FALSE, if the function was to be reduced to a simple memcpy()
  306. // --> In that case, VOSF is not necessary
  307. bool Screen_blitter_init(XVisualInfo * visual_info, bool native_byte_order)
  308. {
  309.     visualFormat.depth = visual_info->depth;
  310.     visualFormat.Rmask = visual_info->red_mask;
  311.     visualFormat.Gmask = visual_info->green_mask;
  312.     visualFormat.Bmask = visual_info->blue_mask;
  313.     
  314.     // Compute RGB shift values
  315.     visualFormat.Rshift = 0;
  316.     for (uint32 Rmask = visualFormat.Rmask; Rmask && ((Rmask & 1) != 1); Rmask >>= 1)
  317.         ++visualFormat.Rshift;
  318.     visualFormat.Gshift = 0;
  319.     for (uint32 Gmask = visualFormat.Gmask; Gmask && ((Gmask & 1) != 1); Gmask >>= 1)
  320.         ++visualFormat.Gshift;
  321.     visualFormat.Bshift = 0;
  322.     for (uint32 Bmask = visualFormat.Bmask; Bmask && ((Bmask & 1) != 1); Bmask >>= 1)
  323.         ++visualFormat.Bshift;
  324.     
  325.     // Search for an adequate blit function
  326.     bool blitter_found = false;
  327.     const int blitters_count = sizeof(Screen_blitters)/sizeof(Screen_blitters[0]);
  328.     for (int i = 0; !blitter_found && (i < blitters_count); i++) {
  329.         if    (    (visualFormat.depth == Screen_blitters[i].depth)
  330.             &&    (visualFormat.Rmask == Screen_blitters[i].Rmask)
  331.             &&    (visualFormat.Gmask == Screen_blitters[i].Gmask)
  332.             &&    (visualFormat.Bmask == Screen_blitters[i].Bmask)
  333.             )
  334.         {
  335.             blitter_found = true;
  336.             Screen_blit = native_byte_order
  337.                         ? Screen_blitters[i].handler_nbo
  338.                         : Screen_blitters[i].handler_obo
  339.                         ;
  340.         }
  341.     }
  342.     
  343.     // No appropriate blitter found, dump RGB mask values and abort()
  344.     if (!blitter_found) {
  345.         fprintf(stderr, "### No appropriate blitter found\n");
  346.         fprintf(stderr, "\tR/G/B mask values  : 0x%06x, 0x%06x, 0x%06x (depth = %d)\n",
  347.             visualFormat.Rmask, visualFormat.Gmask, visualFormat.Bmask, visualFormat.depth);
  348.         fprintf(stderr, "\tR/G/B shift values : %d/%d/%d\n",
  349.             visualFormat.Rshift, visualFormat.Gshift, visualFormat.Bshift);
  350.         abort();
  351.     }
  352.     
  353.     // If the blitter simply reduces to a copy, we don't need VOSF in DGA mode
  354.     // --> In that case, we return FALSE
  355.     return (Screen_blit != Blit_Copy_Raw);
  356. }
  357. #endif /* ENABLE_VOSF */
  358.